home *** CD-ROM | disk | FTP | other *** search
-
- /* Generated by Interface Builder */
-
- #import "PCHPlot.h"
- #import "LPCView.h"
- #import "Dispatcher.h"
- #import <appkit/Application.h>
- #import <appkit/Window.h>
- #import <appkit/ScrollView.h>
- #import <appkit/Panel.h>
- #import <appkit/Cell.h>
- #import <appkit/SavePanel.h>
- #import <appkit/OpenPanel.h>
- #import <strings.h>
- #import <sys/types.h>
- #import <sys/stat.h>
- #import <sys/file.h>
- #import <libc.h>
- #import <dpsclient/dpsclient.h>
- #import <math.h>
- #import <sound/sound.h>
- #import <stdio.h>
- #import <streams/streams.h>
- #import <dpsclient/wraps.h>
- #import "PWfft.h"
-
- #define PITCH 0
- #define AMP 1
- #define SIZE 2
-
- #define MAXZOOM 4
- #define MINZOOM -3
-
- @implementation PCHPlot
-
- extern int errno;
-
- + new:(const char *)title
- {
- NXRect aRect;
-
- self = [super new];
- // Set up memory
- PSops = NULL;
- PSAdata = NULL;
- PSPdata = NULL;
- [NXApp loadNibSection:"pchplot.nib" owner:self];
- [myView setDelegate:self];
- [myView setParent:self];
- [myPlot setDelegate:self];
- numBytes = 0;
- zoomfactor = 1;
- curzoom = 0;
- PWinit();
- [self setDirty:NO];
-
- // Set up view dependencies
-
- [myScroll getDocVisibleRect:&aRect];
- [myView setFrame:&aRect];
- [myScroll setDocView:myView];
- [myScroll setHorizScrollerRequired:YES];
- [myScroll setVertScrollerRequired:NO];
-
- // Set the title of the window - filename or Untitled
- strcpy(filename, title);
- if (!strcmp(filename, "Untitled")) {
- hasData = NO;
- [myPlot setTitleAsFilename:"Untitled"];
- [self show:self];
- return self;
- }
- else {
- [myPlot setTitleAsFilename:filename];
- if ([self setPCHfile:filename] < 0) {
- hasData = NO;
- [myPlot setTitleAsFilename:"Untitled"];
- [self show:self];
- return self;
- }
- hasData = YES;
- }
- [self show:self];
- return self;
- }
-
- - (int) setPCHfile:(const char *)file
- {
- struct stat st;
-
- openfd = open(file, O_RDWR, 0);
- if (openfd < 0) {
- [self error:"Could not open input file : ":errno];
- return -1;
- }
- fstat(openfd, &st);
- frames = (st.st_size/(SIZE*(sizeof(float))))-1;
- numBytes = st.st_size;
- [numFrames setIntValue:frames];
- pchData = (float *)malloc(st.st_size);
- if (read(openfd, pchData, st.st_size) < 0) {
- [self error:"Error reading input file : ":errno];
- return -1;
- }
- return 0;
- }
-
- - drawData
- {
- int i, winwidth;
- float yscalea, yscalep, half, zoomsize;
- NXRect viewBounds, visBounds, scrollBounds;
- NXSize scrollSize;
- float amax, amin; // amplitude boundaries
- float ptchmax, ptchmin; // pitch boundaries
- // DPSUserPath stuff
- float bbox[4];
- float *t, *a, *ptch; // temporary variables
- char *o;
-
- // Only draw plot if such information exists
- if (!hasData)
- return self;
-
- amax = MINFLOAT; ptchmax = MINFLOAT;
- amin = MAXFLOAT; ptchmin = MAXFLOAT;
-
- t = pchData;
- for (i = 0; i < frames; i++) {
- if (t[AMP] > amax)
- amax = t[AMP];
- if (t[AMP] < amin)
- amin = t[AMP];
- if (t[PITCH] > ptchmax)
- ptchmax = t[PITCH];
- if (t[PITCH] < ptchmin)
- ptchmin = t[PITCH];
- t += SIZE;
- }
- if (amax == amin) {
- if (amax > 0)
- amin = 0;
- else if (amax == 0)
- amin = -1;
- else
- amin = 2*amax;
- }
- if (ptchmax == ptchmin) {
- if (ptchmax > 0)
- ptchmin = 0;
- else if (ptchmax == 0)
- ptchmin = -1;
- else
- ptchmin = 2*ptchmax;
- }
-
- [myView getBounds:&viewBounds];
- [myView getVisibleRect:&visBounds];
- [myScroll getContentSize:&scrollSize];
-
- [myScroll getDocVisibleRect:&scrollBounds];
- [myView getVisibleRect:&visBounds];
- scrollBounds.size.width *= zoomfactor;
- /* Bug in DSPUserpath makes drawing at > 4096 bomb */
- while (scrollBounds.size.width > 4096.0) {
- // Simulate a zoom out
- scrollBounds.size.width /= zoomfactor;
- --curzoom;
- zoomfactor /= 1.5;
- scrollBounds.size.width *= zoomfactor;
- printf("too big -- new width = %f\n", scrollBounds.size.width);
- }
- [myView sizeTo:scrollBounds.size.width :scrollBounds.size.height];
- [myView getBounds:&viewBounds];
- [myView lockFocus];
- PSsetgray(NX_WHITE);
- NXRectFill(&viewBounds);
- [myView unlockFocus];
- winwidth = scrollBounds.size.width;
- zoomsize = frames;
- step = 1.0*zoomsize/winwidth;
- half = 1.0*(visBounds.size.height)/2.0;
- yscalea = 1.0*(half - 25.0)/(1.0*(amax - amin));
- yscalep = 1.0*(half - 25.0)/(1.0*(ptchmax - ptchmin));
- if (!PSAdata) PSAdata = (float *)malloc(4*winwidth*sizeof(float));
- if (!PSPdata) PSPdata = (float *)malloc(4*winwidth*sizeof(float));
- if (!PSops) PSops = (char *)malloc(2*winwidth*sizeof(char));
-
- t = pchData;
- for (i = 0, a = PSAdata, ptch = PSPdata, o = PSops;
- i < winwidth; i++) {
- *a++ = i;
- *a++ = 20.0;
- *a++ = 0.0;
- *a++ = ((t[AMP] - amin)*yscalea);
-
- *ptch++ = i;
- *ptch++ = half+20.0;
- *ptch++ = 0.0;
- *ptch++ = ((t[PITCH] - ptchmin)*yscalep);
- *o++ = dps_moveto;
- *o++ = dps_rlineto;
-
- t = (pchData) + (SIZE * (int)(i * step));
- }
- bbox[0] = 0.0;
- bbox[1] = 0.0;
- bbox[2] = winwidth;
- bbox[3] = ((amax - amin)*yscalea) + half;
- [myView drawPlot:PSAdata:PSops:bbox:winwidth:NX_BLACK];
- bbox[1] = half;
- bbox[3] = visBounds.size.height;
- [myView drawPlot:PSPdata:PSops:bbox:winwidth:NX_BLACK];
- PWdrawruler(0, frames,(20*frames/winwidth), (20*frames/winwidth)/step);
- if (PSAdata) free(PSAdata);
- if (PSPdata) free(PSPdata);
- if (PSops) free(PSops);
- PSAdata = NULL;
- PSPdata = NULL;
- PSops = NULL;
- return self;
- }
-
- - show:sender
- {
- [myPlot makeKeyAndOrderFront:self];
- [myView display];
- return self;
- }
-
- - zoomIn:sender
- {
- NXRect foo;
-
- if (curzoom >= MAXZOOM)
- return self;
- [myView getBounds:&foo];
- if ((foo.size.width * 1.5) > 4096.0)
- return self;
- ++curzoom;
- zoomfactor *= 1.5;
- [myView display];
- return self;
- }
-
- - zoomOut:sender
- {
- if (curzoom <= MINZOOM)
- return self;
- --curzoom;
- zoomfactor /= 1.5;
- [myView display];
- return self;
- }
-
- - print:sender
- {
- [myView printPSCode:sender];
- return self;
- }
-
- - updateCursor:sender
- {
- float amp, pitch, *t;
- int cursor, width, frame1, frame2, temp;
-
- if (!hasData)
- return self;
- cursor = [myView getcurPos];
- width = [myView getWidth];
-
- frame1 = (int)(cursor * step);
- frame2 = (int)((cursor + width) * step);
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- [startFrame setIntValue:frame1];
- [endFrame setIntValue:frame2];
- t = pchData + (SIZE * (int)((cursor + width) * step));
- amp = t[AMP];
- pitch = t[PITCH];
- [ampFrame setFloatValue:amp];
- [pitchFrame setFloatValue:pitch];
- [playFrame1 setIntValue:(frame1 + 1)];
- [playFrame2 setIntValue:(frame2 + 1)];
- return self;
- }
-
- - selectAll:sender
- {
- [myView changeCurs:0:(frames/step)];
- [playFrame1 setIntValue:1];
- [playFrame2 setIntValue:(frames+1)];
- return self;
- }
-
- - cursorSel:sender
- {
- [myView setCursorType:SELECTION];
- return self;
- }
-
- - cursorHair:sender
- {
- [myView setCursorType:HAIRLINE];
- return self;
- }
-
- - changeCursor:sender
- {
- int frame1, frame2, temp;
- float loc, loc2, width;
-
- frame1 = [startFrame intValue];
- frame2 = [endFrame intValue];
-
- frame1 = (frame1 < 0) ? 0 : frame1;
- frame1 = (frame1 > frames) ? frames : frame1;
- frame2 = (frame2 < 0) ? 0 : frame2;
- frame2 = (frame2 > frames) ? frames : frame2;
-
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
-
- loc = frame1 / step;
- loc2 = frame2 / step;
- width = loc2 - loc;
- [myView changeCurs:loc:width];
- return self;
- }
-
- - changeAmp:sender
- {
- float *t, val;
- int cursor, width, i, frame1, frame2, temp;
-
- cursor = [myView getcurPos];
- width = [myView getWidth];
- frame1 = (int)cursor * step;
- frame2 = (int)(cursor + width) * step;
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- t = pchData + (SIZE * frame1);
- val = [ampFrame floatValue];
- [self saveundo:(frame2 - frame1 + 1)*SIZE*sizeof(float):t];
- for (i = frame1; i <= frame2; i++) {
- t[AMP] = val;
- t = (pchData) + (SIZE * (i + 1));
- }
- [myView display];
- [self setDirty:YES];
- return self;
- }
-
- - changePitch:sender
- {
- float *t, val;
- int cursor, width, i, frame1, frame2, temp;
-
- cursor = [myView getcurPos];
- width = [myView getWidth];
- frame1 = (int)cursor * step;
- frame2 = (int)(cursor + width) * step;
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- t = pchData + (SIZE * frame1);
- val = [pitchFrame floatValue];
- [self saveundo:(frame2 - frame1 + 1)*SIZE*sizeof(float):t];
- for (i = frame1; i <= frame2; i++) {
- t[PITCH] = val;
- t = (pchData) + (SIZE * (i + 1));
- }
- [myView display];
- [self setDirty:YES];
- return self;
- }
-
- - doCopy:(NXStream *)selection
- {
- float *t;
- int cursor, width, frame1, frame2, temp, bytes;
-
- if (!hasData) {
- return self;
- }
- cursor = [myView getcurPos];
- width = [myView getWidth];
- frame1 = (int)cursor * step;
- frame2 = (int)(cursor + width) * step;
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- t = pchData + (SIZE * frame1);
- bytes = (frame2 - frame1)*SIZE*sizeof(float);
- NXWrite(selection, t, bytes);
- return self;
-
- }
-
- - doCut:(NXStream *)selection
- {
- float *t, *v;
- int cursor, width, i, frame1, frame2, temp, bytes;
-
- if (!hasData) {
- return self;
- }
- cursor = [myView getcurPos];
- width = [myView getWidth];
- frame1 = (int)cursor * step;
- frame2 = (int)(cursor + width) * step;
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- t = pchData + (SIZE * frame1);
- bytes = (frame2 - frame1)*SIZE*sizeof(float);
- NXWrite(selection, t, bytes);
- numBytes -= bytes;
- frames = (numBytes/(SIZE*sizeof(float)))-1;
- [numFrames setIntValue:frames];
- v = t + (bytes / sizeof(float));
- for (i = 0; i < (bytes / sizeof(float)); i++) {
- *t++ = *v++;
- }
- realloc(pchData, numBytes);
- [myView display];
- [self setDirty:YES];
- return self;
-
- }
-
- - doInsert:(float *)data :(int) bytes
- {
- int cursor, frame1, size, i;
- float *t, *v;
-
- if (!hasData) {
- hasData = 1;
- pchData = (float *)malloc(bytes);
- numBytes = bytes;
- frames = (numBytes/(SIZE*sizeof(float))) - 1;
- [numFrames setIntValue:frames];
- t = pchData;
- for (i = 0; i < (bytes / sizeof(float)); i++) {
- *t++ = *data++;
- }
- [myView display];
- return self;
- }
- numBytes += bytes;
- frames = (numBytes/(SIZE*sizeof(float)))-1;
- [numFrames setIntValue:frames];
- realloc(pchData, numBytes);
- cursor = [myView getcurPos];
- frame1 = (int)cursor * step;
- size = (numBytes - bytes) - (frame1 * SIZE * sizeof(float));
-
- v = pchData + (numBytes / sizeof(float)) - 1;
- t = pchData + ((numBytes - bytes) / sizeof(float)) - 1;
- for (i = 0; i < (size / sizeof(float)); i++) {
- *v-- = *t--;
- }
- t = pchData + (SIZE * frame1);
- for (i = 0; i < (bytes / sizeof(float)); i++) {
- *t++ = *data++;
- }
- [myView display];
- [self setDirty:YES];
- return self;
- }
-
- - saveundo:(int)size: (float *)data
- {
- int i;
- float *t, *s;
-
- if (undoData)
- free(undoData);
- undoData = (float *)malloc(size);
- undoLoc = data;
- undoSize = size;
- t = undoData;
- s = data;
- for (i = 0; i < (undoSize / 4); i++) {
- *t++ = *s++;
- }
- return self;
- }
-
- - undo:sender
- {
- float *t, *s;
- int i;
-
- t = undoLoc;
- s = undoData;
- for (i = 0; i < (undoSize / 4); i++) {
- *t++ = *s++;
- }
- [myView display];
- return self;
- }
-
- - multiplyAmp:sender
- {
- float *t, val;
- int cursor, width, i, frame1, frame2, temp;
-
- cursor = [myView getcurPos];
- width = [myView getWidth];
- frame1 = (int)cursor * step;
- frame2 = (int)(cursor + width) * step;
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- val = [mulAmpFrame floatValue];
- t = pchData + (SIZE * frame1);
- [self saveundo:(frame2 - frame1 + 1)*SIZE*sizeof(float):t];
- for (i = frame1; i <= frame2; i++) {
- t[AMP] *= val;
- t = (pchData) + (SIZE * (i + 1));
- }
- [myView display];
- [self setDirty:YES];
- return self;
- }
-
- - multiplyPitch:sender
- {
- float *t, val, top, bottom;
- int cursor, width, i, frame1, frame2, temp;
-
- cursor = [myView getcurPos];
- width = [myView getWidth];
- t = pchData + (SIZE * (int)(cursor * step));
- frame1 = (int)cursor * step;
- frame2 = (int)(cursor + width) * step;
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- val = [mulPitchFrame floatValue];
- top = [topPitchFrame floatValue];
- bottom = [botPitchFrame floatValue];
- t = pchData + (SIZE * frame1);
- [self saveundo:(frame2 - frame1 + 1)*SIZE*sizeof(float):t];
- for (i = frame1; i <= frame2; i++) {
- if (t[PITCH] <= top && t[PITCH] >= bottom)
- t[PITCH] *= val;
- t = (pchData) + (SIZE * (i + 1));
- }
- [myView display];
- [self setDirty:YES];
- return self;
- }
-
- - interpolate:sender
- {
- float *t, *v, first, last, scale;
- int cursor, width, i, frame1, frame2, temp, j;
-
- cursor = [myView getcurPos];
- width = [myView getWidth];
- frame1 = ((int)(cursor * step)) - 1;
- frame2 = ((int)((cursor + width) * step)) + 1;
- if (frame1 > frame2) {
- temp = frame1;
- frame1 = frame2;
- frame2 = temp;
- }
- t = pchData + (SIZE * frame1);
- v = pchData + (SIZE * frame2);
- first = t[PITCH];
- last = v[PITCH];
- t = pchData + (SIZE * frame1);
- scale = (last - first) / (frame2 - frame1);
- [self saveundo:(frame2 - frame1 + 1)*SIZE*sizeof(float):t];
- for (i = frame1, j = 0; i <= frame2; i++) {
- t[PITCH] = first + (j * scale);
- t = (pchData) + (SIZE * (i + 1));
- ++j;
- }
- [myView display];
- [self setDirty:YES];
- return self;
- }
-
- - save:sender
- {
- id sPanel;
-
- sPanel = [SavePanel new];
- if (!strcmp("Untitled", filename)) {
- if ([sPanel runModal]) {
- strcpy(filename, [sPanel filename]);
- [myPlot setTitleAsFilename:filename];
- openfd = open(filename, O_RDWR|O_CREAT, 0644);
- if (openfd < 0) {
- [self error:"Error opening input file : ":errno];
- return self;
- }
- if (write(openfd, (char *)pchData, numBytes) < 0) {
- [self error:"Error writing file : ":errno];
- return self;
- };
- [self setDirty:NO];
- return self;
- }
- }
- else {
- lseek(openfd, 0, 0); // start of file
- if (write(openfd,(char *)pchData,numBytes) < 0) {
- [self error:"Error writing file : ":errno];
- return self;
- }
- [self setDirty:NO];
- return self;
- }
- return self;
- }
-
- - saveAs:sender
- {
- id sPanel;
- char dir[1024], *file;
-
- sPanel = [SavePanel new];
- file = rindex(filename, '/') + 1;
- strncpy(dir, filename, (int)(file - filename));
- if ([sPanel runModalForDirectory:dir file:file]) {
- if (strcmp(filename, [sPanel filename])) {
- strcpy(filename, [sPanel filename]);
- close(openfd);
- openfd = open(filename, O_RDWR|O_CREAT, 0644);
- if (openfd < 0) {
- [self error:"Error saving file : ":errno];
- return self;
- }
- if (write(openfd, (char *)pchData, numBytes) < 0) {
- [self error:"Error saving file : ":errno];
- return self;
- }
- [myPlot setTitleAsFilename:filename];
- [self setDirty:NO];
- return self;
- }
- else {
- lseek(openfd, 0, 0);
- if (write(openfd, (char *)pchData, numBytes) < 0) {
- [self error:"Error saving file : ":errno];
- return self;
- }
- [self setDirty:NO];
- return self;
- }
- }
- return self;
- }
-
- - setOutputFile:sender
- {
- id openP;
- char *types[2];
-
- types[0] = "snd";
- types[1] = 0;
- openP = [OpenPanel new];
- [openP runModalForTypes:types];
- if ([openP filenames]) {
- strcpy(soundFilename, [openP filename]);
- [soundFileFrame setStringValue:soundFilename];
- }
- return self;
- }
-
- - playOutputSound:sender
- {
- int err;
- SNDSoundStruct *s;
-
- strcpy(soundFilename, [soundFileFrame stringValue]);
- if (!strlen(soundFilename))
- return self;
- err = SNDReadSoundfile(soundFilename, &s);
- if (!err) {
- err = SNDStartPlaying(s, 1, 5, 0, 0,(SNDNotificationFun)SNDFree);
- if (!err)
- SNDWait(1);
- else
- [self error:"Error playing soundfile":0];
- }
- else {
- [self error:"Error reading soundfile":0];
- }
- return self;
- }
-
- - play:sender
- {
- return self;
- }
-
- - doPitchAnal:sender
- {
- char cmd[1024];
-
- strcpy(soundFilename, [soundFileFrame stringValue]);
- if (!strlen(soundFilename)) {
- strcpy(soundFilename, "/tmp/anal.snd");
- [soundFileFrame setStringValue:soundFilename];
- }
- sprintf(cmd, "%s %s %s %d %d", [NXApp playpitch], filename, soundFilename, [playFrame1 intValue], [playFrame2 intValue]);
- system(cmd);
- return self;
- }
-
- - drawPlot:sender
- {
- return self;
- }
-
- - plot
- {
- return myPlot;
- }
-
- - error:(char *)msg:(int)num
- {
- if (num)
- NXRunAlertPanel("Alert", "%s : %s", "OK", NULL, NULL, msg, strerror(num));
- else
- NXRunAlertPanel("Alert", "%s", "OK", NULL, NULL, msg);
- return self;
- }
-
- - windowWillClose:sender
- {
- if ([myPlot isDocEdited]) {
- switch (NXRunAlertPanel("Alert", "Plot has been edited. Do you want to save?", "Yes", "No", "Cancel")) {
- case NX_ALERTDEFAULT :
- [self saveAs:self];
- break;
- case NX_ALERTOTHER :
- return nil;
- break;
- default :
- break;
- }
- }
- return self;
- }
-
- - setDirty:(BOOL)val
- {
- [myPlot setDocEdited:val];
- dirty = val;
- return self;
- }
-
- - (BOOL)isDirty
- {
- return dirty;
- }
-
- @end
-